package repositories

import (
	"database/sql"
	"gameTest/common"
	"gameTest/datamodels"
	"math"
	"strconv"
)

type IProduct interface {
	//连接数据库
	Conn() error
	Insert(*datamodels.Product) (int64, error)
	Delete(int64) bool
	Update(*datamodels.Product) error
	SelectByKey(int64) (*datamodels.Product, error)
	SelectAll() ([]*datamodels.Product, error)
	SelectList(where string, page int64, prePage int64) (datamodels.ResultList, error)
	Count(where string) (count int64, err error)
}

type ProductManager struct {
	table     string
	mysqlConn *sql.DB
}

func NewProductManager(table string, db *sql.DB) IProduct {
	return &ProductManager{table: table, mysqlConn: db}
}

//数据库连接
func (p *ProductManager) Conn() (err error) {
	if p.mysqlConn == nil {
		mysql, err := common.NewMysqlConn()
		if err != nil {
			return err
		}
		p.mysqlConn = mysql
	}
	if p.table == "" {
		p.table = "product"
	}
	return
}

//插入
func (p *ProductManager) Insert(product *datamodels.Product) (productId int64, err error) {
	if err = p.Conn(); err != nil {
		return
	}
	sql := "INSERT product SET product_name = ?, product_num = ? , product_image = ?, product_url = ?, create_at = ?, update_at = ?"
	stmt, errSql := p.mysqlConn.Prepare(sql)
	if errSql != nil {
		return 0, errSql
	}
	result, errStmt := stmt.Exec(product.ProductName, product.ProductNum, product.ProductImage, product.ProductUrl, product.CreateAt, product.UpdateAt)
	if errStmt != nil {
		return 0, errStmt
	}
	productId, err = result.LastInsertId()
	return
}

//删除
func (p *ProductManager) Delete(productId int64) bool {
	if err := p.Conn(); err != nil {
		return false
	}
	sql := "DELETE FROM product WHERE id = ?"
	stmt, err := p.mysqlConn.Prepare(sql)
	if err != nil {
		return false
	}
	_, err = stmt.Exec(productId)
	if err != nil {
		return false
	}
	return true
}

//修改
func (p *ProductManager) Update(product *datamodels.Product)  error {
	if err := p.Conn(); err != nil {
		return  err
	}
	sql := "UPDATE product SET product_name = ?, product_num = ?, product_image = ?, product_url = ?, update_at = ? WHERE id =" + strconv.FormatInt(product.ID, 10)
	stmt, err := p.mysqlConn.Prepare(sql)
	if err != nil {
		return  err
	}
	_, err = stmt.Exec(product.ProductName, product.ProductNum, product.ProductImage, product.ProductUrl, product.UpdateAt)
	if err != nil {
		return  err
	}
	return nil
}

//查询一条
func (p *ProductManager) SelectByKey(productId int64) (productResult *datamodels.Product, err error) {
	if err = p.Conn(); err != nil {
		return  &datamodels.Product{}, err
	}
	sql := "SELECT * FROM " + p.table + " WHERE id = " + strconv.FormatInt(productId, 10)
	row, errRow := p.mysqlConn.Query(sql)
	defer  row.Close()
	if errRow != nil {
		return &datamodels.Product{}, errRow
	}
	result := common.GetResultRow(row)
	if len(result) == 0 {
		return  &datamodels.Product{}, nil
	}
	productResult = &datamodels.Product{}
	common.DataToStructByTagSql(result, productResult)
	return
}
//查询全部产品
func (p *ProductManager) SelectAll() (productArray []*datamodels.Product, errProduct error)  {
	if err := p.Conn(); err != nil {
		return  nil, err
	}
	sql := "SELECT * FROM " + p.table
	rows, err := p.mysqlConn.Query(sql)
	defer rows.Close()
	if err != nil {
		return  nil, err
	}
	result := common.GetResultRows(rows)
	if len(result) == 0 {
		return nil, nil
	}
	for _, v := range result {
		product := &datamodels.Product{}
		common.DataToStructByTagSql(v, product)
		productArray = append(productArray, product)
	}
	return
}

//分页查找
func (p *ProductManager) SelectList(where string, page int64, prePage int64) (data datamodels.ResultList, err error) {
	if err := p.Conn(); err != nil {
		return data, err
	}
	count, errCount := p.Count(where)
	if errCount != nil {
		return
	}

	if count == 0 {
		data.Total = count
		data.Page = page
		data.PrePage = prePage
		return data, nil
	}

	totalPage := int64(math.Ceil(float64(count) / float64(prePage)))
	prePageStr := strconv.FormatInt(prePage, 10)
	offset := ( page - 1) * prePage
	offsetStr := strconv.FormatInt(offset, 10)

	sql := "SELECT * FROM " + p.table + " WHERE " + where + " LIMIT " + offsetStr +  " , " + prePageStr
	rows, err := p.mysqlConn.Query(sql)
	defer rows.Close()
	if err != nil {
		return data, err
	}
	result := common.GetResultRows(rows)
	if len(result) == 0 {
		return
	}
	var productArray []*datamodels.Product
	for _, v := range result {
		product := &datamodels.Product{}
		common.DataToStructByTagSql(v, product)
		productArray = append(productArray, product)
	}
	data.Total = count
	data.Page = page
	data.PrePage = prePage
	data.TotalPage = totalPage
	data.Lists = productArray
	return
}

//查询全部
func (p *ProductManager) Count(where string) (count int64, err error){
	sql := "SELECT COUNT(*) FROM " + p.table + " WHERE " + where
	rows, err := p.mysqlConn.Query(sql)
	defer rows.Close()
	if err != nil {
		return  0, err
	}
	if rows.Next() {
		rows.Scan(&count)
	}
	return
}